#pragma rtGlobals=1		// Use modern global access method.
#include <WaveSelectorWidget>

//-------------------------------------------------------------------------------------------------------------------------------------------------------------------

Function genericWaveSelection(windowName, panelTop, panelBottom, panelLeft, panelRight, listPosX, listPosY, listSizeX, listSizeY)
String windowName
Variable panelTop, panelBottom, panelLeft, panelRight, listPosX, listPosY, listSizeX, listSizeY
String/G root:Packages:waveSelectionReturnList = ""

DoWindow/K Wave_Browser

NewPanel /W=(panelLeft,panelTop,panelRight,panelBottom)/N=Wave_Browser as windowName
ListBox waveSelectionBox,pos={listPosX,listPosY},size={listSizeX, listSizeY}
MakeListIntoWaveSelector("Wave_Browser", "WaveSelectionBox", selectionMode=WMWS_SelectionSingle, content=WMWS_Waves)
Button waveSelectionButton title="Select Wave", size={80,20}, proc=waveSelectionButton_Proc
Button waveSelectionCancel title="Cancel", size={80,20}, proc=waveSelectCancel_Proc
SetWindow Wave_Browser, hook(windowCancel_Hook) = waveSelectHookFunction_Cancel
ModifyPanel fixedSize=1
end

//-------------------------------------------------------------------------------------------------------------------------------------------------------------------

Function waveSelectionButton_Proc(ctrlName) : ButtonControl
	String ctrlName
	SVAR waveSelectionReturnList = root:Packages:waveSelectionReturnList
	waveSelectionReturnList = WS_SelectedObjectsList("Wave_Browser", "waveSelectionBox")
	DoWindow/K Wave_Browser
End

//-------------------------------------------------------------------------------------------------------------------------------------------------------------------

Function genericCancel_Proc(B_Struct) : ButtonControl
	STRUCT WMButtonAction &B_Struct
	Variable/G root:Packages:mouseDownEvent
	NVAR mouseDownEvent = root:Packages:mouseDownEvent
	If(B_Struct.eventCode == 1)
		mouseDownEvent = 1
	endif
	If(B_Struct.eventCode == 2 && mouseDownEvent == 1)
		mouseDownEvent = 0
		DoWindow/K $B_Struct.win
	endif
End

//-------------------------------------------------------------------------------------------------------------------------------------------------------------------

Function windowHookFunction_Cancel(s)
STRUCT WMWinHookStruct &s
	If(s.eventCode == 17)
		DoWindow/K $s.WinName
		return 1
	endif
end

//-------------------------------------------------------------------------------------------------------------------------------------------------------------------

Function waveSelectCancel_Proc(s) :ButtonControl
STRUCT WMButtonAction &s

//WS_ClearSelection("Wave_Browser", "waveSelectionBox")
genericCancel_Proc(s)

end

//-------------------------------------------------------------------------------------------------------------------------------------------------------------------

Function waveSelectHookFunction_Cancel(s)
STRUCT WMWinHookStruct &s

//WS_ClearSelection("Wave_Browser", "waveSelectionBox")
windowHookFunction_Cancel(s)

end

//-------------------------------------------------------------------------------------------------------------------------------------------------------------------

Function matrixConvolution(inputWaveStr, energyWaveStr, guassWidthIn, lorentWidthIn, typeOfConvolution)
String inputWaveStr,  energyWaveStr
Variable guassWidthIn, lorentWidthIn, typeOfConvolution
Wave inputWave = $inputWaveStr, energyWave = $energyWaveStr

Variable delta, guassWidth, lorentWidth

If(stringMatch(energyWaveStr, "") == 0)
	delta = (Wavemax(energyWave) - Wavemin(energywave))/numpnts(energyWave)
else
	delta = (pnt2x(inputWave, numpnts(inputWave)) - pnt2x(inputWave,0))/numpnts(inputWave)
endif

guassWidth = guassWidthIn/delta
lorentWidth = lorentWidthIn/delta

Make/O/N=(dimsize(inputWave,0)) blardp, guassTemp, lorenTemp, func

guassWidth = guassWidth/(2*sqrt(2*ln(2)))

guassTemp = exp(-0.5*((x-dimsize(inputWave,0)/2)/(guassWidth))^2)  
lorenTemp = (1/pi)*(lorentWidth/2)/((x-dimsize(inputWave,0)/2)^2 + (lorentWidth/2)^2)

If(guassWidth != 0 && lorentWidth != 0)
	Duplicate/O guassTemp, func
	Convolve/A lorenTemp, func
elseif(guassWidth != 0 && lorentWidth == 0)
	func = guassTemp
elseif(guassWidth == 0 && lorentWidth != 0)
	func = lorenTemp
endif

blardp = func

If(typeOfConvolution == 1)
	Make/O/N=(dimsize(inputWave,0),dimsize(inputWave,0)) funcMat
	funcMat[][] = func[p + dimsize(func,0)/2 - q]
	Wave w1 = inputWave
elseif(typeOfConvolution == 2)
	 Make/O/N=(dimsize(inputWave,0),dimsize(inputWave,0)) funcMat
	funcMat[][] = func[mod(p + dimsize(func,0)/2 - q, numpnts(func))]
	Wave w1 = inputWave
elseif(typeOfConvolution == 0)
	Duplicate/O inputWave, $"inputWave_samp"
	InsertPoints 0,dimsize(inputWave,0)/4, inputWave_samp
	Make/O/N=(ceil(dimsize(inputWave_samp,0)/2),dimsize(inputWave_samp,0)) funcMat
	funcMat[][] = func[p + dimsize(func,0) - q]
	Wave w1 = inputWave_samp
endif

MatrixOP/O $inputWaveStr + "_conv" = funcMat x w1

end

Function dupTraceSubRange(targetGraph, lowX, highX, multipule, offset)
String targetGraph
Variable lowX, highX, multipule, offset

String listOfTraces = TraceNameList(targetGraph,";",1)
Variable numberOfTraces = itemsInList(listOfTraces)
Variable p1,p2,p3
For(p1 = 0; p1 < numberOfTraces; p1 += 1)
	String currentTrace = stringFromList(p1, listOfTraces)
	String currentTraceInfo = TraceInfo(targetGraph,currentTrace,traceInstance(currentTrace))
	For(p2 = 0; p2 < itemsinlist(currentTraceInfo,":") - 1; p2 += 1)
		String tempKey = stringFromList(p2, currentTraceInfo, ";")
		tempKey = tempKey[0,strsearch(tempKey, ":",0)-1]
		if(!stringMatch(tempKey,"RECREATION"))
			String currentTraceInfoValue = StringByKey(tempKey,currentTraceInfo)
		else
			String modifyTraceValue =  StringFromList(p2+1,currentTraceInfo,":")
			String newCurrentTrace = currentTrace
			String newlistOfTraces = TraceNameList(targetGraph,";",1)
			//If(!traceInstance(currentTrace))
			//	newCurrentTrace += "#1"
			//else
				Variable instanceNum = 0
				Do
					instanceNum += 1
					if(strsearch(currentTrace,"#",0) == -1)
						newCurrentTrace = currentTrace + "#" + num2str(instanceNum)
					else
						newCurrentTrace = ReplaceString(currentTrace[strlen(currentTrace)-2,inf],currentTrace,"#" + num2str(instanceNum))
					endif
				while(FindListItem(newCurrentTrace,newlistOfTraces) != -1)
				Variable lowPnt = x2pnt(TraceNameToWaveRef(targetGraph,currentTrace),highX)
				Variable highPnt = x2pnt(TraceNameToWaveRef(targetGraph,currentTrace),lowX)
			AppendToGraph TraceNameToWaveRef(targetGraph,currentTrace)[lowPnt,highPnt]
			For(p3 = 0 ; p3 < itemsinlist(modifyTraceValue); p3 += 1)
				String tempModifyTraceValue = stringFromList(p3, modifyTraceValue)
				tempModifyTraceValue = ReplaceString("(x)",tempModifyTraceValue,"(" + newCurrentTrace + ")")
				Execute "ModifyGraph " + tempModifyTraceValue
			endFor
			Execute "ModifyGraph muloffset(" + newCurrentTrace + ")={0," + num2str(multipule) + "}"
			Execute "ModifyGraph offset(" + newCurrentTrace + ")={0," + num2str(offset) + "}"
		endif
	endFor
endFor
end

Function traceInstance(traceName)
String traceName
	Variable result = (Strsearch(traceName,"#",0)==-1)
	if(result)
		Return 0
	else
		Return str2num(traceName[Strsearch(traceName,"#",0)+1,inf])
	endif
end

Function/S getTraceInfo(targetGraph, traceName)
String targetGraph, traceName
String currentTraceInfo = TraceInfo(targetGraph,traceName,traceInstance(traceName))
String tempKey = ""
Variable p1 = 0
Do
	tempKey = StringFromList(p1,currentTraceInfo,":")
	p1 += 1
While(!stringMatch(tempKey,";RECREATION"))
Return StringFromList(p1,currentTraceInfo,":")
end

Function shiftWavesFromTrace(targetGraph,flag)
String targetGraph
Variable flag
Preferences 1
If(!strlen(targetGraph))
	targetGraph = WinName(0,1)
endIf
String listOfTraces = TraceNameList(targetGraph,";",1)
Variable numberOfTraces = itemsInList(listOfTraces), currentXoffSet, currentYoffset, currentYscale
Variable p1
String currentTrace,currentTraceInfo, currentTraceXwave = "null"
For(p1 = 0; p1 < numberOfTraces; p1 += 1)
	currentTrace = stringFromList(p1, listOfTraces)
	currentTraceInfo = getTraceInfo(targetGraph,currentTrace)
	Wave tempWave = TraceNameToWaveRef(targetGraph,currentTrace)
	if(WaveExists(XWaveRefFromTrace(targetGraph,currentTrace)))
		Wave tempXWave = XWaveRefFromTrace(targetGraph,currentTrace)
		currentTraceXWave = NameOfWave(TempXwave)
	else
		Wave tempXWave = $""
		currentTraceXWave = "null"
	endif
	sscanf StringByKey("offset(x)",currentTraceInfo,"=",";"),"{%f,%f}",currentXoffSet,currentYoffSet
	sscanf StringByKey("muloffset(x)",currentTraceInfo,"=",";"),"{%*f,%f}",currentYScale
	if(!currentYScale)
		currentYScale = 1
	endif
	Duplicate/O tempWave, $(GetWavesDataFolder(tempWave,2) + "_s")
	Wave tempWaveShift = $(GetWavesDataFolder(tempWave,2) + "_s")
	tempWaveShift *= currentYScale
	tempWaveShift += currentYoffSet
	if(WaveExists(XWaveRefFromTrace(targetGraph,currentTrace)))
		Duplicate/O tempXWave, $(GetWavesDataFolder(tempXWave,2) + "_s")
		Wave tempXwaveShift =  $(GetWavesDataFolder(tempXWave,2) + "_s")
		tempXWaveShift += currentXoffSet
	else
		Wave tempXwaveShift =  $""
		Setscale/I x,pnt2x(tempWave,0) + currentXoffSet,pnt2x(tempWave, numpnts(tempWave)-1) + currentXoffSet,tempWaveShift
	endif
	if(flag)
		newGraphSameStyle(tempWaveShift, NameOfWave(tempXWaveShift), targetGraph, currentTrace)
	else
		saveShiftedDataFromGraph(tempWaveShift, NameOfWave(tempXWaveShift), targetGraph, currentTrace)
	endif
endfor
Preferences 0
end

Function newGraphSameStyle(inputWave, inputXWaveName, targetGraph, traceName, [typeOfGraph])
Wave inputWave
String inputXWaveName
String targetGraph, traceName
Variable typeOfGraph
String newGraph = targetGraph + "_s"
If(typeOfGraph)
	newGraph = targetGraph + "_scale"
endIf
if(!strlen(inputXwaveName))
	if(itemsinList(WinList(newGraph,";",""),";"))
		AppendToGraph/W=$newGraph inputWave
	else
		Display/N=$newGraph inputWave
	endif
else
	Wave inputXWave = $(GetWavesDataFolder(XWaveRefFromTrace(targetGraph,traceName),2))
	if(itemsinList(WinList(newGraph,";",""),";"))
		AppendToGraph/W=$newGraph inputWave vs inputXwave
	else
		Display/N=$newGraph inputWave vs inputXwave
	endif
endif

String currentTraceList = TraceNameList(newGraph,";",1)
String currentTraceName = StringFromList(itemsinlist(currentTraceList)-1,currentTraceList,";")
Variable p1
String traceInfoList = getTraceInfo(targetGraph, traceName)
For(p1 = 0; p1 < itemsInList(traceInfoList); p1 += 1)
	String tempModifyTraceValue = stringFromList(p1, traceInfoList)
	tempModifyTraceValue = ReplaceString("(x)",tempModifyTraceValue,"(" + currentTraceName + ")")
	Execute "ModifyGraph " + tempModifyTraceValue
endfor
	Execute "ModifyGraph muloffset(" + currentTraceName + ")={0,0}"
	Execute "ModifyGraph offset(" + currentTraceName + ")={0,0}"
end

Function mergeGraphs(graphList, outputGraphName)
String graphList, outputGraphName
Variable p1
For(p1 = 0; p1 < itemsInList(graphlist); p1 += 1)
	
endFor
end

Function saveShiftedDataFromGraph(inputWave, inputXWaveName, targetGraph, traceName)
Wave inputWave
String inputXWaveName, targetGraph,traceName
if(strlen(inputXwaveName))
	Wave inputXWave = $(GetWavesDataFolder(XWaveRefFromTrace(targetGraph,traceName),1) + inputXWaveName)
endif
If(!strlen(targetGraph))
	targetGraph = WinName(0,1)
endIf
String noteName = ReplaceString("#", traceName, "_")
NewNotebook/N=$(noteName + "_")/K=1/F=0/V=0 as "DataOut"
Notebook $(noteName + "_") setdata = ParseFilePath(0,GetWavesDataFolder(TraceNameToWaveRef(targetGraph,traceName),2),":",1,1)
Notebook $(noteName + "_") setdata = "\rEnergy\t\tIntensity\r"
Variable p1, energy
String dataHolderString
For(p1 = 0; p1 < numpnts(inputWave); p1 += 1)
	if(strlen(inputXwaveName))
		sprintf dataHolderString, "%.4f\t\t%.15f\r", inputXWave[p1], inputWave[p1]
	else
		energy = p1*DimDelta(inputWave,0) + DimOffset(inputWave,0)
		sprintf dataHolderString, "%.4f\t\t%.15f\r", energy, inputWave[p1]
	endif
	Notebook $(noteName + "_") setdata=dataHolderString
endfor
if(Exists("ProgressPanel"))
	TitleBox titledisp0,title=("Saving " + (ParseFilePath(0,GetWavesDataFolder(inputWave,2),":",1,1) + "_" + ParseFilePath(3,GetWavesDataFolder(inputWave,2),":",0,0) + ".dat")),win=ProgressPanel,pos={19,11}
endif
SaveNotebook/P=notebookSavePath $(WinName(0,16)) as (ParseFilePath(0,GetWavesDataFolder(inputWave,2),":",1,1) + "_" + ParseFilePath(3,GetWavesDataFolder(inputWave,2),":",0,0) + ".dat")
DoWindow/K $(noteName + "_")
//SavePICT/E=-5/B=576/N=$targetGraph/O/P=notebookSavePath as targetGraph + ".png"
end

Function saveDataFromSomeGraphs(graphListString)
String graphListString
If(!strlen(graphListString))
	graphListString = WinName(0,1) + ";"
endIf
Variable p1
NewPanel /N=ProgressPanel /W=(1509,488,1888,559)
ValDisplay valdisp0,pos={18,32},size={342,18},limits={0,1,0},barmisc={0,0},mode=4
ValDisplay valdisp0,value= _NUM:1,highColor=(0,0,0)
For(p1 = 0; p1 < itemsinList(graphListString); p1 += 1)
	String savePath = findUserHome() + "\\My Documents\\WaveMetrics\\Igor Pro 6 User Files\\Data"
	NewPath/C/Q/Z/O notebookSavePath, savePath
	savePath = findUserHome() + "\\My Documents\\WaveMetrics\\Igor Pro 6 User Files\\Data\\" + stringfromlist(p1, graphlistString) 
	NewPath/C/Q/Z/O notebookSavePath, savePath
	TitleBox titledisp0,title=("Saving " + stringfromlist(p1, graphlistString)),win=ProgressPanel,pos={19,11},frame=0
	SavePICT/E=-5/B=576/N=$stringfromlist(p1, graphlistString) /O/P=notebookSavePath as stringfromlist(p1, graphlistString) + ".png"
	shiftWavesFromTrace(stringFromList(p1, graphListString),0)
	ValDisplay valdisp0,value= _NUM:1,win=ProgressPanel
endFor
KillWindow ProgressPanel
end

Function getDateFromWaveNote(inputWave)
Wave inputWave
if(WaveExists(inputWave))
Variable year, month, day
sscanf StringByKey("Date",note(inputWave), "=","\r"), "%f/%f/%f", month, day, year
Return date2secs(year, month, day)
else
Return 0
endif
end

Function getDateFromVersaWaveNote(inputWave)
Wave inputWave
Variable year, month, day
sscanf StringByKey("FileDate",note(inputWave), ":","\r"), "%f %f %f", year, month, day
Return date2secs(year, month, day)
end

Function getTimeFromWaveNote(inputWave)
Wave inputWave
If(WaveExists(inputWave))
String period
Variable hours, minutes, seconds
sscanf StringByKey("Time",note(inputWave), "=","\r"), "%f:%f:%f %s", hours, minutes, seconds, period
if(StringMatch(period, "AM"))
	if(hours == 12)
		hours = 0
	endif
else
	if(hours != 12)
		hours += 12
	endif
endif
Return hours*60*60 + minutes*60 + seconds
Else
Return 0
endif
end

Function getDateTimeFromWaveNote(inputWave)
Wave inputWave
Return getDateFromWaveNote(inputWave) + getTimeFromWaveNote(inputWave)
end

Function/S FindNearestGoldScans(inputWave, scanType)
Wave inputWave
String scanType
Variable targetDataTime = getDateTimeFromWaveNote(inputWave)
if(exists("root:Packages:closestAboveStr"))
		KillVariables root:Packages:closestAbove,root:Packages:closestBelow
		KillStrings root:Packages:closestAboveStr,root:Packages:closestBelowStr
endif
getDateTimesFromAllScans("root:", scanType, "", inputWave)
SVAR aboveScan = root:Packages:closestAboveStr, belowScan = root:Packages:closestBelowStr
aboveScan += scanType
belowScan += scanType
Return (aboveScan + ";" + belowScan)
end

Function/S FindNearestVersaScans(inputWave, scanType)
Wave inputWave
String scanType
Variable targetDataTime = getDateTimeFromWaveNote(inputWave)
if(exists("root:Packages:closestScanStr"))
		KillVariables root:Packages:closestScan
		KillStrings root:Packages:closestScanStr
endif
getDateFromAllVersaScans(":::", scanType, "", inputWave)
SVAR aboveScan = root:Packages:closestScanStr
Return (aboveScan)
end

Function getDateTimesFromAllScans(path, waveListMatchStr, waveListOptionsStr, inputWave)
	String path				// to walk all data folders, pass "root:" WITH the : char. To use the current data folder, use ":" or GetDataFolder(1)
	String waveListMatchStr		// "*" or "wave*" or "!*x", etc. See WaveList for details.
	String waveListOptionsStr	// usually "". see WaveList's optionsStr for details.
	Wave inputWave
	NewDataFolder/O root:Packages
	if(!exists("root:Packages:closestAboveStr"))
		Variable/G root:Packages:closestAbove = inf,root:Packages:closestBelow = -inf
		String/G root:Packages:closestAboveStr,root:Packages:closestBelowStr
	endif
	NVAR closestAbove =  root:Packages:closestAbove, closestBelow = root:Packages:closestBelow
	SVAR closestAboveStr =  root:Packages:closestAboveStr, closestBelowStr = root:Packages:closestBelowStr
	
	String savDF= GetDataFolder(1)
	SetDataFolder path

	String listOfMatchingWaves= WaveList(waveListMatchStr,";",waveListOptionsStr)
	Variable p1
	
	For(p1 = 0; p1 < itemsInList(listOfMatchingWaves); p1 += 1)
		Wave tempWave = $stringFromList(p1,listOfMatchingWaves)
		If(dimsize(tempwave,1) == 0)
		Variable timeDiff = -(getDateTimeFromWaveNote(inputWave) - getDateTimeFromWaveNote(tempWave))
		If( timeDiff > closestBelow && timeDiff <= 0)
			closestBelow = timeDiff
			closestBelowStr = GetDataFolder(1)
		endif
		If(timeDiff < closestAbove && timeDiff > 0)
			closestAbove = timeDiff
			closestAboveStr = GetDataFolder(1)
		endif
		endif
	endFor

	Variable i, numDataFolders = CountObjects(":",4)
	for(i=0; i<numDataFolders; i+=1)
		String nextPath = GetIndexedObjName(":",4,i)
		getDateTimesFromAllScans(nextPath, waveListMatchStr, waveListOptionsStr, inputWave)
	endfor
	SetDataFolder savDF
End

Function getDateFromAllVersaScans(path, waveListMatchStr, waveListOptionsStr, inputWave)
	String path				// to walk all data folders, pass "root:" WITH the : char. To use the current data folder, use ":" or GetDataFolder(1)
	String waveListMatchStr		// "*" or "wave*" or "!*x", etc. See WaveList for details.
	String waveListOptionsStr	// usually "". see WaveList's optionsStr for details.
	Wave inputWave
	NewDataFolder/O root:Packages
	if(!exists("root:Packages:closestScan"))
		Variable/G root:Packages:closestScan = inf
		String/G root:Packages:closestScanStr = ""
	endif
	NVAR closestScan =  root:Packages:closestScan
	SVAR closestScanStr =  root:Packages:closestScanStr
	
	String savDF= GetDataFolder(1)
	SetDataFolder path

	String listOfMatchingWaves= WaveList(waveListMatchStr,";",waveListOptionsStr)
	Variable p1
	For(p1 = 0; p1 < itemsInList(listOfMatchingWaves); p1 += 1)
		Wave tempWave = $stringFromList(p1,listOfMatchingWaves)
		
		Variable timeDiff = -(getDateFromVersaWaveNote(inputWave) - getDateFromVersaWaveNote(tempWave))
		//If(timeDiff == 0 && (stringmatch(NameOfWave(tempWave),"C1s*") || stringmatch(NameOfWave(tempWave),"Au4f*")))
		If(timeDiff == 0)
			closestScan = timeDiff
			closestScanStr = AddListItem(GetWavesDataFolder(tempWave,2), closestScanStr, ";", inf)
			//Print/D GetWavesDataFolder(inputWave,2), getDateFromVersaWaveNote(inputWave)
			//Print/D GetWavesDataFolder(tempWave,2), getDateFromVersaWaveNote(tempWave)
		endif
	endFor

	Variable i, numDataFolders = CountObjects(":",4)
	for(i=0; i<numDataFolders; i+=1)
		String nextPath = GetIndexedObjName(":",4,i)
		getDateFromAllVersaScans(nextPath, waveListMatchStr, waveListOptionsStr, inputWave)
	endfor
	SetDataFolder savDF
End

Function getPhotonEnergyFromGoldVB(inputWave)
Wave inputWave
EdgeStats/Q/F=.2 inputWave
Return V_EdgeLoc1
end

Function getPhotonEnergyFromGold4f(inputWave)
Wave inputWave
if(WaveExists(inputWave))
FindPeak/Q/B=2/M=(.9*WaveMax(inputWave)) inputWave
If(V_flag)
	//Print "No peak found for: " + GetWavesDataFolder(inputWave,2)
	Return 0
else
	Return V_PeakLoc + 84.0
endif
else
	Return 0
endif
end

Function getPhotonEnergyFromCarbon1s(inputWave)
Wave inputWave
FindPeak/Q/B=2/M=(.9*WaveMax(inputWave)) inputWave
If(V_flag)
	Print "No peak found for: " + GetWavesDataFolder(inputWave,2)
	Return 0
else
	//Print/D GetWavesDataFolder(inputWave,2), V_PeakLoc
	Return V_PeakLoc + 285.4
endif
end


Function doShiftFromGoldVB(inputWave)
Wave inputWave
String goldScanList = FindNearestGoldScans(inputWave, "Au_VB")
Variable goldAbove = getPhotonEnergyFromGoldVB($(stringFromList(0,goldScanList))), goldBelow = getPhotonEnergyFromGoldVB($(stringFromList(1,goldScanList)))
Variable goldAboveTimeDiff = abs(getDateTimeFromWaveNote(inputWave) - getDateTimeFromWaveNote($(stringFromList(0,goldScanList))))
Variable goldBelowTimeDiff = abs(getDateTimeFromWaveNote(inputWave) - getDateTimeFromWaveNote($(stringFromList(1,goldScanList))))
Variable goldTimeDiff = abs(getDateTimeFromWaveNote($(stringFromList(0,goldScanList))) - getDateTimeFromWaveNote($(stringFromList(1,goldScanList))))
Duplicate/O inputWave, $(GetWavesDataFolder(inputWave,2) + "_ShiftVB")
Wave tempWaveShift = $(GetWavesDataFolder(inputWave,2) + "_ShiftVB")
Variable photonEnergy = (goldBelow*(1-(goldBelowTimeDiff/goldTimeDiff))+goldAbove*(1-(goldAboveTimeDiff/goldTimeDiff)))
Note tempWaveShift, "Au VB Shift= " + num2str(photonEnergy)
//Variable photonEnergy = goldBelow
Print/D GetWavesDataFolder(inputWave,2), GetWavesDataFolder($(stringFromList(0,goldScanList)),2), GetWavesDataFolder($(stringFromList(1,goldScanList)),2), goldAbove, goldBelow, photonEnergy
Setscale/I x,(photonEnergy -pnt2x(tempWaveShift,0)),(photonEnergy - pnt2x(tempWaveShift,numpnts(tempWaveShift))), tempWaveShift 
end

Function doShiftFromGold4f(inputWave, [is1D])
Wave inputWave
Variable is1D
String goldScanList
If( ParamIsDefault(is1D) || is1D==0)
	goldScanList = FindNearestGoldScans(inputWave, "Au4f")
elseif(is1D == 1)
	goldScanList = FindNearestGoldScans(inputWave, "Au4f_1D")
else
	goldScanList =  FindNearestGoldScans(inputWave, "Au4f_Ecorr_1D")
endif
Variable goldAbove = getPhotonEnergyFromGold4f($(stringFromList(0,goldScanList))), goldBelow = getPhotonEnergyFromGold4f($(stringFromList(1,goldScanList)))
Variable goldAboveTimeDiff = abs(getDateTimeFromWaveNote(inputWave) - getDateTimeFromWaveNote($(stringFromList(0,goldScanList))))
Variable goldBelowTimeDiff = abs(getDateTimeFromWaveNote(inputWave) - getDateTimeFromWaveNote($(stringFromList(1,goldScanList))))
Variable goldTimeDiff = abs(getDateTimeFromWaveNote($(stringFromList(0,goldScanList))) - getDateTimeFromWaveNote($(stringFromList(1,goldScanList))))
Duplicate/O inputWave, $(GetWavesDataFolder(inputWave,2) + "_Shift4f")
Wave tempWaveShift = $(GetWavesDataFolder(inputWave,2) + "_Shift4f")
Variable photonEnergy = (goldBelow*(1-(goldBelowTimeDiff/goldTimeDiff))+goldAbove*(1-(goldAboveTimeDiff/goldTimeDiff)))
Note tempWaveShift, "Ref Scan Before: " + stringFromList(0,goldScanList)
String tempString
Sprintf tempString,"Ref Scan Before Time Difference= %.0f mins, %.1f sec", (floor(goldAboveTimeDiff/60)), mod(goldAboveTimeDiff,60) 
Note tempWaveShift, tempString
Sprintf tempString,"Au4f Shift Before= %.5f eV", goldAbove
Note tempWaveShift, tempString
Note tempWaveShift, "Ref Scan After: " + stringFromList(1,goldScanList)
Sprintf tempString,"Ref Scan After Time Difference= %.0f mins, %.1f sec", (floor(goldBelowTimeDiff/60)), mod(goldBelowTimeDiff,60) 
Note tempWaveShift, tempString
Sprintf tempString,"Au4f Shift After= %.5f eV", goldBelow
Note tempWaveShift, tempString
if(goldTimeDiff < 3600)
	photonEnergy = (goldBelow*(1-(goldBelowTimeDiff/goldTimeDiff))+goldAbove*(1-(goldAboveTimeDiff/goldTimeDiff)))
ElseIf(goldAboveTimeDiff <= goldBelowTimeDiff)
	photonEnergy = goldAbove
else
	photonEnergy = goldBelow
endif
Sprintf tempString,"Au4f Shift Used= %.5f eV", photonEnergy
Note tempWaveShift, tempString
//Print/D GetWavesDataFolder(inputWave,2), GetWavesDataFolder($(stringFromList(0,goldScanList)),2), GetWavesDataFolder($(stringFromList(1,goldScanList)),2), goldAbove, goldBelow, photonEnergy
Setscale/I x,(photonEnergy -pnt2x(tempWaveShift,0)),(photonEnergy - pnt2x(tempWaveShift,numpnts(tempWaveShift)-1)), tempWaveShift 
end

Function doShiftFromCarbon1s(inputWave)
Wave inputWave
String goldScanList = FindNearestGoldScans(inputWave, "C1s")
Duplicate/O inputWave, $(GetWavesDataFolder(inputWave,2) + "_ShiftC1s")
Wave tempWaveShift = $(GetWavesDataFolder(inputWave,2) + "_ShiftC1s")
Variable photonEnergy = getPhotonEnergyFromCarbon1s($(stringFromList(1,goldScanList)))
//Print goldScanList, GetWavesDataFolder(inputWave,2)
//Print stringFromList(0,goldScanList), stringFromList(1,goldScanList), GetWavesDataFolder(inputWave,2)
Note tempWaveShift, "C1s Shift= " + num2str(photonEnergy)
//Print/D GetWavesDataFolder(inputWave,2), photonEnergy
Setscale/I x,(photonEnergy -pnt2x(tempWaveShift,0)),(photonEnergy - pnt2x(tempWaveShift,numpnts(tempWaveShift) -1)), tempWaveShift 
end

Function doShiftVersaProbeAu4f(inputWave)
Wave inputWave
String ScanType ="Au4f*"
String calibrationScanList = FindNearestVersaScans(inputWave, scanType)
Variable p1,p2
Variable/G root:Packages:selectedShift
NVAR selectedShift = root:Packages:selectedShift
Make/O/N=(itemsinList(CalibrationScanList)) root:Packages:shiftValuesWave
Wave shiftValuesWave = root:Packages:shiftValuesWave
For(p1 = 0; p1 < itemsinlist(calibrationScanList); p1 += 1)
	Wave tempWave = $StringFromList(p1,calibrationScanList)
	FindPeak/Q/B=10/M=(.8*WaveMax(tempWave)) tempWave
	//Print GetWavesDataFolder(tempWave,2), V_peakLoc
	if(V_flag)
		Print "No peak found for: " + GetWavesDataFolder(tempWave,2)
		shiftValuesWave[p1] = 0
	else
		shiftValuesWave[p1] = 84.0 - V_peakLoc
	endif
endFor
Make/O/N=(numpnts(shiftValuesWave))/T root:Packages:listBoxSelectionWave
Wave/T listBoxSelectionWave = root:Packages:listBoxSelectionWave
For(p1 = 0; p1 < numpnts(shiftValuesWave); p1 += 1)
	listBoxSelectionWave[p1] = StringFromList(p1,CalibrationScanList)
endFor
String ScanList = FindNearestVersaScans(inputWave, "!*_VersaShift")

if(wintype("selectBox") != 0)
	DoWindow/F selectBox
elseif(wintype("selectBox") == 0)
	NewPanel/N=selectBox/W=(150,77,665,250)/K=1 as "Select Reference Wave"
	ListBox list0,win=selectBox,pos={1,2},size={512,135}
	ListBox list0,win=selectBox,listWave=root:Packages:listBoxSelectionWave,mode= 2,selRow= 0
	Button referenceWaveSelection title="Select", proc=referenceWaveSelectionButton
	ModifyPanel fixedSize=1
endif
PauseForUser selectBox

For(p1 = 0; p1 < itemsinlist(ScanList); p1 += 1)
	Wave newTempWave = $stringfromList(p1,ScanList)
	Duplicate/O newTempWave, $(GetWavesDataFolder(newTempWave,2) + "_VSAu4f")
	Wave tempWaveShift = $(GetWavesDataFolder(newTempWave,2) + "_VSAu4f")
	Note tempWaveShift, "Au4f Shift: " + num2str(selectedShift)
	Setscale/I x,(selectedShift + pnt2x(tempWaveShift,0)),(selectedShift + pnt2x(tempWaveShift,numpnts(tempWaveShift))), tempWaveShift 
endFor
end

Function doShiftVersaProbeC1s(inputWave)
Wave inputWave
String ScanType ="C1s"
String calibrationScanList = FindNearestVersaScans(inputWave, scanType)
Variable p1,p2
Variable/G root:Packages:selectedShift
NVAR selectedShift = root:Packages:selectedShift
Make/O/N=(itemsinList(CalibrationScanList)) root:Packages:shiftValuesWave
Wave shiftValuesWave = root:Packages:shiftValuesWave
For(p1 = 0; p1 < itemsinlist(calibrationScanList); p1 += 1)
	Wave tempWave = $StringFromList(p1,calibrationScanList)
	FindPeak/Q/B=4/M=(.9*WaveMax(tempWave)) tempWave
	//Print GetWavesDataFolder(tempWave,2), V_peakLoc
	if(V_flag)
		Print "No peak found for: " + GetWavesDataFolder(tempWave,2)
		shiftValuesWave[p1] = 0
	else
		//Print/D "Found peak at: ", V_peakLoc
		shiftValuesWave[p1] = 285.4 - V_peakLoc
	endif
endFor
calibrationScanList = FindNearestVersaScans(inputWave, scanType)
For(p1 = 0; p1 < itemsInList(calibrationScanList); p1 += 1)
	String currentCalibration = ParseFilePath(0, stringfromList(p1,calibrationScanList), ":", 1, 1)
	String currentSelectedWave = ParseFilePath(0, GetWavesDataFolder(inputWave,2), ":", 1, 1)
	if(StringMatch(currentCalibration, currentSelectedWave) ||  getDateFromVersaWaveNote(inputWave) ==  getDateFromVersaWaveNote($stringfromList(p1,calibrationScanList)))
		//Print/D currentSelectedWave, currentCalibration, shiftValuesWave
		Duplicate/O inputWave, $(GetWavesDataFolder(inputWave,2) + "_VSC1s")
		Wave inputTempWave = $(GetWavesDataFolder(inputWave,2) + "_VSC1s")
		Note inputTempWave, "C1s Shift: " + num2str(shiftValuesWave[p1])
		Setscale/I x,(shiftValuesWave[p1] + pnt2x(inputTempWave,0)),(shiftValuesWave[p1] + pnt2x(inputTempWave,numpnts(inputTempWave))), inputTempWave
	endif
endFor
end

Function referenceWaveSelectionButton(s) :ButtonControl
	Struct WMButtonAction &s
	NVAR selectedShift = root:Packages:selectedShift
	Wave shiftValuesWave = root:Packages:shiftValuesWave
	If(s.eventCode == 2)
		ControlInfo/W=selectBox list0
		selectedShift = shiftValuesWave[V_value]
		KillWindow selectBox
	endif
End

Function plotSomeWavesFromFolders(path, inputWaveListStr)
	String path				
	String inputWaveListStr		

	String savDF= GetDataFolder(1)
	SetDataFolder path
	
	Variable numberOfWavesInFolder = CountObjects(":",1)
	Variable numberOfWavesToPlot = itemsInList(inputWaveListStr)
	Variable p1, p2, totalMatches = 0
	String IndexList = ""
	SVAR folderList = root:folderList
	if(!Exists("countWave"))
		Make/O/N=(numberOfWavesToPlot) countWave
		countWave = 0
	elseif(numpnts(countWave) != numberOfWavesToPlot)
		Make/O/N=(numberOfWavesToPlot) countWave
		countWave = 0
	endif
	
	For(p1 = 0; p1 < numberOfWavesToPlot; p1 += 1)
		For(p2 = 0; p2 < numberOfWavesInFolder; p2 += 1)
			//totalMatches += StringMatch(stringFromList(p1, inputWaveListStr), GetIndexedObjName(":",1,p2))
			countWave[p1] += GrepString(GetIndexedObjName(":",1,p2), stringFromList(p1, inputWaveListStr))
			If(StringMatch(stringFromList(p1, inputWaveListStr), GetIndexedObjName(":",1,p2)))
				IndexList = addListItem(num2str(p2),IndexList,";",inf)
			endif
		endFor
	endFor
	Print countWave
	
	Variable everyWavePresent = 1
	
	For(p1 = 0;p1 < numberOfWavesToPlot; p1 += 1)
		if(countWave[p1] == 0)
			everyWavePresent = 0
		endif
	endFor
	
	//If(totalMatches >= numberOfWavesToPlot)
	If(everyWavePresent)
		//Display/K=1 $GetIndexedObjName(":",1,str2num(stringFromList(0,IndexList))) as GetDataFolder(0)
		folderList = AddListItem(GetDataFolder(0),folderList,";",inf)
		For(p1 = 1; p1 < numberOfWavesToPlot; p1 += 1)
			//AppendToGraph $GetIndexedObjName(":",1,str2num(stringFromList(p1,IndexList)))
		endFor
	endif
	
	Variable i, numDataFolders = CountObjects(":",4)
	for(i=0; i<numDataFolders; i+=1)
		String nextPath = GetIndexedObjName(":",4,i)
		countWave = 0
		plotSomeWavesFromFolders(nextPath, inputWaveListStr)
	endfor

	SetDataFolder savDF
end

Function makeWavesFromList(inputStrList, numberPnts)
String inputStrList
Variable numberPnts
Variable p1

For(p1 = 0; p1 < itemsinlist(inputStrList); p1 += 1)
	String newWaveName = ReplaceString("-",stringFromList(p1, inputStrList),"_")
	newWaveName = ReplaceString("\'",newWaveName,"")
	newWaveName = ReplaceString("\"",newWaveName,"")
	Make/N=(numberPnts) $newWaveName
endFor
end

Function GetOffSetsFromTrace(targetGraph,flag)
String targetGraph
Variable flag
String listOfTraces = TraceNameList(targetGraph,";",1)
Variable numberOfTraces = itemsInList(listOfTraces), currentXoffSet, currentYoffset, currentYscale, currentXscale
Variable p1
String currentTrace,currentTraceInfo, currentTraceXwave = "null", XoffsetList = "", YoffsetList = "", YscaleList = "", XscaleList = "", NameOfWaveList = ""
For(p1 = 0; p1 < numberOfTraces; p1 += 1)
	currentTrace = stringFromList(p1, listOfTraces)
	currentTraceInfo = getTraceInfo(targetGraph,currentTrace)
	Wave tempWave = TraceNameToWaveRef(targetGraph,currentTrace)
	if(WaveExists(XWaveRefFromTrace(targetGraph,currentTrace)))
		Wave tempXWave = XWaveRefFromTrace(targetGraph,currentTrace)
		currentTraceXWave = NameOfWave(TempXwave)
	else
		Wave tempXWave = $""
		currentTraceXWave = "null"
	endif
	NameOfWaveList = AddListItem(NameOfWave(tempWave),NameOfWaveList,";",inf)
	sscanf StringByKey("offset(x)",currentTraceInfo,"=",";"),"{%f,%f}",currentXoffSet,currentYoffSet
	sscanf StringByKey("muloffset(x)",currentTraceInfo,"=",";"),"{%f,%f}",currentXscale,currentYScale
	XoffSetList = AddListItem(num2Str(currentXoffSet),XoffSetList,";",inf)
	YoffSetList = AddListItem(num2Str(currentYoffSet),YoffSetList,";",inf)
	if(!currentYScale)
		currentYScale = 1
	endif
	if(!currentXScale)
		currentXScale = 1
	endif
	XscaleList = AddListItem(num2str(currentXScale),XscaleList,";",inf)
	YscaleList = AddListItem(num2str(currentYScale),YscaleList,";",inf)
	Print/D GetWavesDataFolder(tempWave,2),","+currentTrace
	if(flag & 2^0)
		Print/D "  \t X offset:",currentXoffSet
	endif
	if(flag & 2^1)
		Print/D "\t Y offset: ",currentYoffSet
	endif
	if(flag & 2^2)
		Print/D "\t X scale: ",currentXScale
	endif
	if(flag & 2^3)
		Print/D "\t Y scale: ",currentYScale
	endif
endfor
end

Menu "TracePopup"
		"Hide Trace", /Q, HideTrace()
		"Plot Trace vs Top", /Q, DupTraceAxisTop()
		"Apply Shift", /Q, ApplyTraceShiftAllGraphsWaves()
End

Function HideTrace()
	GetLastUserMenuInfo
	//Print S_traceName
	//Print S_graphName
	ModifyGraph /W=$S_graphName hideTrace($S_traceName)=1
End

Function PrintPath()
	GetLastUserMenuInfo
	Print GetWavesDataFolder(TraceNameToWaveRef(S_graphName,S_traceName),0)
End

Function DupTraceAxisTop()
	GetLastUserMenuInfo
	Wave selectedYWave = TraceNameToWaveRef(S_graphName,S_traceName)
	Wave selectedXWave = XWaveRefFromTrace(S_graphName,S_traceName)
	If(Exists("selectedXWave"))
		AppendtoGraph/T/W=$S_graphName selectedYWave vs selectedXWave
	Else
		AppendtoGraph/T/W=$S_graphName selectedYWave
	endIf
End

Function DrawZeroLine()
	SetDrawEnv xcoord=prel, ycoord=left
	Drawline 0,0,1,0
end

Function subRangeWaveFromTraces(targetGraph,xMin,xMax)
String targetGraph
Variable xMin,xMax
String listOfTraces = TraceNameList(targetGraph,";",1), currentTrace,currentTraceInfo,currentTraceXWave
Variable numberOfTraces = itemsInList(listOfTraces), currentXoffSet, currentYoffset, currentYscale,pntXMin,pntXMax,pntMin
Variable p1
DFREF savDFR = GetDataFolderDFR(), waveDFR
For(p1 = 0; p1 < numberOfTraces; p1 += 1)
	currentTrace = stringFromList(p1, listOfTraces)
	currentTraceInfo = getTraceInfo(targetGraph,currentTrace)
	Wave tempWave = TraceNameToWaveRef(targetGraph,currentTrace)
	waveDFR = GetWavesDataFolderDFR(tempWave)
	SetDataFolder waveDFR
	sscanf StringByKey("offset(x)",currentTraceInfo,"=",";"),"{%f,%f}",currentXoffSet,currentYoffSet
	sscanf StringByKey("muloffset(x)",currentTraceInfo,"=",";"),"{%*f,%f}",currentYScale
	if(!currentYScale)
		currentYScale = 1
	endif
	if(WaveExists(XWaveRefFromTrace(targetGraph,currentTrace)))
		Wave tempXWave = XWaveRefFromTrace(targetGraph,currentTrace)
		currentTraceXWave = NameOfWave(TempXwave)
		FindValue/V=(xMin - currentXoffSet) tempXWave
		pntXMin = V_value
		FindValue/V=(xMax - currentXoffSet) tempXWave
		pntXMax = V_value
		pntMin = Min(pntXMax,pntXMin)
		Make/O/N=(abs(pntXMax-pntXMin)) $(currentTraceXWave + "_cut"),$(NameOfWave(tempWave)+ "_cut")
		Wave cutXWave =  $(currentTraceXWave + "_cut"), cutYWave = $(NameOfWave(tempWave)+ "_cut")
		cutXWave[] = tempXwave[p+pntMin]
	else
		Wave tempXWave = $""
		currentTraceXWave = "null"
		pntXMin = x2pnt(tempWave,xMin-currentXoffSet)
		pntXMax = x2pnt(tempWave,xMax-currentXoffSet)
		pntMin = Min(pntXMax,pntXMin)
		Make/O/N=(abs(pntXMax-pntXMin)) $(NameOfWave(tempWave)+ "_cut")
		Wave cutYWave = $(NameOfWave(tempWave)+ "_cut")
		If(pntXMax-pntXMin >= 0)
			SetScale/I x,xMin,xMax,cutYwave
		else
			SetScale/I x,xMax,xMin,cutYwave
		endif
	endif
	cutYwave[] = tempWave[p+pntMin]*currentYScale+currentYoffSet
endfor
SetDataFolder savDFR
end

//Dynamic menus for the contextual menu
Menu  "TraceGraphMenu", contextualmenu, dynamic
	"Duplicate Graph", DuplicateTopGraph()
	"IdentifyTraces",/Q, GetTraces()
End

Menu "GraphMarquee2", contextualmenu, dynamic
	"Expand", /Q, marqueeZoom(2^0+2^1)
	"Horiz Expand", /Q, marqueeZoom(2^1)
	"Vert Expand", /Q, marqueeZoom(2^0)
	"Shrink", /Q
	"Horiz Shrink", /Q,
	"Vert Shrink", /Q, 
End
 
Menu  "GraphMenu", contextualmenu, dynamic
		"Append Traces to Graph...", doIgorMenu "graph", "Append Traces to Graph"
		"Remove From Graph...", doIgorMenu "graph", "Remove From Graph"
		"-"
		"Modify Graph...", doIgorMenu "graph", "Modify Graph"
		traceCheck(), doIgorMenu "graph","Modify Trace Appearance"
		ReorderCheck(), doIgorMenu "graph","Reorder Traces"
		ContourCheck(), doIgorMenu "graph","Modify Contour Appearance"
		ImageCheck(), doIgorMenu "graph","Modify Image Appearance"
		"-"
		"Autoscale Axes", doIgorMenu "graph", "AutoScale Axes"
		"Axis Properties", doIgorMenu "graph", "Modify Axis"
 		"-"
		"Add Annotation", doIgorMenu "graph","Add Annotation"
		"-"
		Submenu "Colors"
		Submenu "graph background" 
			CurrentColor(), /Q, SetSelectedColor(2^0)
		
		end
		Submenu "window background"
			CurrentColor(), /Q, SetSelectedColor(2^1)
		
		end
		Submenu "both backgrounds" 
			CurrentColor(), /Q, SetSelectedColor(2^0+2^1)
		
		end
		Submenu "all axis"
			CurrentColor(), /Q, SetSelectedColor(2^2)
		
		end
		Submenu "all grids"
			CurrentColor(), /Q, SetSelectedColor(2^3)
		
		end
		Submenu "all tick labels"
			CurrentColor(), /Q, SetSelectedColor(2^4)
		
		end
		Submenu "all axis labels"
			CurrentColor(), /Q, SetSelectedColor(2^5)
		
		end
		End
		"-"
		Submenu "Frame"
		Submenu "Style"
			FrameStyleMenuItem(0), /Q, SetSelectedFrame(0)
			FrameStyleMenuItem(1), /Q, SetSelectedFrame(1)
			FrameStyleMenuItem(2), /Q, SetSelectedFrame(2)
			FrameStyleMenuItem(3), /Q, SetSelectedFrame(3)
			FrameStyleMenuItem(4), /Q, SetSelectedFrame(4)
			FrameStyleMenuItem(5), /Q, SetSelectedFrame(5)
			FrameStyleMenuItem(6), /Q, SetSelectedFrame(6)
			FrameStyleMenuItem(7), /Q, SetSelectedFrame(7)
		End
		Submenu "Inset"
			FrameInsetMenuItem(0), /Q, SetFrameInset(0)
			FrameInsetMenuItem(1), /Q, SetFrameInset(1)
			FrameInsetMenuItem(2), /Q, SetFrameInset(2)
			FrameInsetMenuItem(3), /Q, SetFrameInset(3)
			FrameInsetMenuItem(4), /Q, SetFrameInset(4)
			FrameInsetMenuItem(5), /Q, SetFrameInset(5)
			FrameInsetMenuItem(6), /Q, SetFrameInset(6)
			FrameInsetMenuItem(7), /Q, SetFrameInset(7)
			FrameInsetMenuItem(8), /Q, SetFrameInset(8)
			FrameInsetMenuItem(9), /Q, SetFrameInset(9)
			FrameInsetMenuItem(10), /Q, SetFrameInset(10)
		End
		End
		Submenu "Expansion"
			expansionMenuItem(0), /Q, SetExpansion(0)
			expansionMenuItem(1), /Q, SetExpansion(1)
			expansionMenuItem(2), /Q, SetExpansion(2)
			expansionMenuItem(3), /Q, SetExpansion(3)
			expansionMenuItem(4), /Q, SetExpansion(4)
			expansionMenuItem(5), /Q, SetExpansion(5)
			expansionMenuItem(6), /Q, SetExpansion(6)
			expansionMenuItem(7), /Q, SetExpansion(7)
			expansionMenuItem(8), /Q, SetExpansion(8)
			expansionMenuItem(9), /Q, SetExpansion(9)
			expansionMenuItem(10), /Q, SetExpansion(10)
			expansionMenuItem(11), /Q, SetExpansion(11)
			expansionMenuItem(12), /Q, SetExpansion(12)
			expansionMenuItem(13), /Q, SetExpansion(13)
		End
		"-"
		"Curve Fitting...",/Q,doIgorMenu "Analysis","Curve Fitting"
		"-"
		"Toggle Context Menu", /Q, toggleSelectionInAllGraphs()
		"-"
		"New Layout", /Q, doIgorMenu "Windows","New Layout"
		SubMenu "Graph Shortcuts"
		"Draw Zero Line", /Q, DrawZeroLine()
		"Scale Traces", /Q, scaleTracesOnGraph("")
		"Save Shifts", /Q, shiftWavesFromTrace("",1)
		"Apply All Shifts", /Q, applyAllShiftsAllGraphsWaves()
		"Stack Traces", /Q, stackTraces()
		"Plot All Cores", /Q, plotallcores()
		End
		Submenu "Save"
		"Export Graph Data", /Q, saveDataFromSomeGraphs("")
		"Save Graph Image", /Q, doIgorMenu "File","Save Graphics"
		End
		SubMenu "Crosshair"
			SubMenu "Crosshair"
			"A" , /Q, toggleCrossHair("A",1)
			"B" , /Q, toggleCrossHair("B",1)
			"C" , /Q, toggleCrossHair("C",1)
			"D" , /Q, toggleCrossHair("D",1)
			"E" , /Q, toggleCrossHair("E",1)
			"F" , /Q, toggleCrossHair("F",1)
			"G" , /Q, toggleCrossHair("G",1)
			"H" , /Q, toggleCrossHair("H",1)
			"I" , /Q, toggleCrossHair("I",1)
			"J" , /Q, toggleCrossHair("J",1)
			End
			SubMenu "Vertical Crosshair"
			"A" , /Q, toggleCrossHair("A",2)
			"B" , /Q, toggleCrossHair("B",2)
			"C" , /Q, toggleCrossHair("C",2)
			"D" , /Q, toggleCrossHair("D",2)
			"E" , /Q, toggleCrossHair("E",2)
			"F" , /Q, toggleCrossHair("F",2)
			"G" , /Q, toggleCrossHair("G",2)
			"H" , /Q, toggleCrossHair("H",2)
			"I" , /Q, toggleCrossHair("I",2)
			"J" , /Q, toggleCrossHair("J",2)
			End
			SubMenu "Horizontal Crosshair"
			"A" , /Q, toggleCrossHair("A",3)
			"B" , /Q, toggleCrossHair("B",3)
			"C" , /Q, toggleCrossHair("C",3)
			"D" , /Q, toggleCrossHair("D",3)
			"E" , /Q, toggleCrossHair("E",3)
			"F" , /Q, toggleCrossHair("F",3)
			"G" , /Q, toggleCrossHair("G",3)
			"H" , /Q, toggleCrossHair("H",3)
			"I" , /Q, toggleCrossHair("I",3)
			"J" , /Q, toggleCrossHair("J",3)
			End
		End
		End
End

Function quickFit(quickFitType, [fitOrder])
string quickFitType
Variable fitOrder
String listOfTraces = TraceNameList("",";",1), currentTrace,currentTraceInfo,currentTraceXWave
Variable numberOfTraces = itemsInList(listOfTraces), selectedTrace
If(numberOfTraces)
	Prompt selectedTrace, "You are trying to use Quick Fit on a graph with more than one trace.\r\nWhich data set do you want to fit?"
	DoPrompt/HELP="" "Test", selectedTrace
endIf

end

Function/S FrameStyleMenuItem(menuItem)
Variable menuItem
Variable p1,checked,frameStyle
String frameStyleStr = StringByKey("framestyle",ReplaceString("\r",WinRecreation("",1),","),"=",",")
If(strlen(frameStyleStr))
	frameStyle = str2num(frameStyleStr)
Else
	frameStyle = 0
endIf

string output = "", listOfStyles = "None;Single;Double;Triple;Shadow;Indented;Raised;Text well"
If(frameStyle == menuItem)
	output = "!" + num2Char(18) + stringFromList(menuItem,listOfStyles)
Else
	output = stringFromList(menuItem,listOfStyles)
endIf
return output
end 

Function SetSelectedFrame(clickedItem)
Variable clickedItem
ModifyGraph frameStyle=clickedItem
end 
 
Function/S FrameInsetMenuItem(menuItem)
Variable menuItem
Variable frameInset
String frameInsetStr = StringByKey("frameInset",ReplaceString("\r",WinRecreation("",1),","),"=",",")
String output
If(strlen(frameInsetStr))
	frameInset = str2num(frameInsetStr)
Else
	frameInset = 0
endIf

If(frameInset == menuItem)
	output = "!" + num2Char(18) + num2str(menuItem)
Else
	output = num2str(menuItem)
endIf
return output
end 
 
Function SetFrameInset(clickedItem)
Variable clickedItem
ModifyGraph frameInset=clickedItem
end

Function/S expansionMenuItem(menuItem)
Variable menuItem
Variable expansionCoef
String expansionCoefStr = StringByKey("expand",ReplaceString("\r",WinRecreation("",1),","),"=",",")
String output, listOfExpansions = "0.125;0.25;0.5;0.667;0.75;None;1.333;1.5;1.75;2;3;4;5;8"
If(strlen(expansionCoefStr))
	expansionCoef = str2num(expansionCoefStr)
Else
	expansionCoef = -1
endIf

If(stringMatch(expansionCoefStr,"-" + stringFromList(menuItem,listOfExpansions)))
	output = "!" + num2Char(18) + stringFromList(menuItem,listOfExpansions)
ElseIf(expansionCoef == -1 && menuItem == 5)
	output = "!" + num2Char(18) + stringFromList(menuItem,listOfExpansions)
Else
	output = stringFromList(menuItem,listOfExpansions)
endIf
return output
end 
 
Function SetExpansion(clickedItem)
Variable clickedItem
String listOfExpansions = "0.125;0.25;0.5;0.667;0.75;None;1.333;1.5;1.75;2;3;4;5;8"
If(clickedItem != 5)
	ModifyGraph expand=str2num(stringFromList(clickedItem,listOfExpansions))
Else
	ModifyGraph expand=0
endIf
end
 
Function/S CurrentColor()
GetLastUserMenuInfo // sets V_red, V_green, V_blue, S_value, V_value
Variable red = V_red,green = V_green,blue = V_blue
String menuText
sprintf menuText, "*COLORPOP*(%d,%d,%d)",red,green,blue
return menuText
End

Function SetSelectedColor(flag)
Variable flag
GetLastUserMenuInfo // sets V_red, V_green, V_blue, S_value, V_value
If(flag & 2^0) 
	ModifyGraph gbRGB=(V_red,V_green,V_blue)
endIf
If(flag & 2^1) 
	ModifyGraph wbRGB=(V_red,V_green,V_blue)
endIf
If(flag & 2^2) 
	ModifyGraph axRGB=(V_red,V_green,V_blue)
endIf
If(flag & 2^3) 
	ModifyGraph gridRGB=(V_red,V_green,V_blue)
endIf
If(flag & 2^4) 
	ModifyGraph tlblRGB=(V_red,V_green,V_blue)
endIf
If(flag & 2^5) 
	ModifyGraph alblRGB=(V_red,V_green,V_blue)
endIf
End 
 
Function Contextualwindowhook(hs)
//Contextual menu code.
//To Create a contextual menu without a premade menu use:
//			PopupcontextualMenu/c =(hs.mouseloc.h, hs.mouseLoc.v) "Select;Deseclect;Hello;"
//			Strswitch(S_selection)
//				case "Select":
//					ModifyGraph swapXY=1
//					break
//				case "Deselect":
//					ModifyGraph swapXY=0
//					break
//				case "hello":
//					print "hello"
//			endswitch
//otherwise use /n and the name of the dynamic menu
	Struct WMWinHookStruct &hs
	Variable ret=0
	strswitch(hs.eventName)
		case "mousedown":
		variable iscontextualmenu = hs.eventmod%& 0x10
		//acontextual click is a right-click on windows or a control-click on MAC 
		if( !isContextualmenu )
			break // allow normal click handling
		endif
		//allows a contextual menu on the trace
		String clickedTraceinfo = TraceFromPixel(hs.mouseLoc.h,HS.MouseLoc.v,"")
		If(Strlen(ClickedTraceInfo))
			string tn=StringbyKey("Trace",ClickedTraceInfo)
			//PopupcontextualMenu/c =(hs.mouseloc.h, hs.mouseLoc.v)/N "TraceGraphMenu"
			GetMarquee/Z
			If(V_flag)
				ret = 1
				break
			endIf
			GetMarquee/Z/K
			break
		else //allows a contextual menu anywhere else on the graph
			GetMarquee/Z
			If(!V_flag)
				PopupcontextualMenu/c =(hs.mouseloc.h, hs.mouseLoc.v)/n "GraphMenu"
				ret = 1
			Else
				//PopupcontextualMenu/c =(hs.mouseloc.h, hs.mouseLoc.v)/n "GraphMarquee2"
				ret = 1
				break
			endIf
			GetMarquee/Z/K
			break
		endif
	endswitch
	return ret
end

Function toggleSelectionInAllGraphs()
NewDataFolder/O/S root:Packages
String graphList = ""
graphList = WinList("*", ";", "WIN:1")		// All graph windows.
Variable p1
If(!exists("root:Packages:selectionToggle"))
	Variable/G root:Packages:selectionToggle = 0
endIf
NVAR selectionToggle = root:Packages:selectionToggle

If(selectionToggle)
	For(p1 = 0; p1 < ItemsInList(graphList); p1 += 1)
		disallowSelectionInGraph(stringFromList(p1,graphList))
	endFor
	selectionToggle = 0
Else
	For(p1 = 0; p1 < ItemsInList(graphList); p1 += 1)
		allowSelectionInGraph(stringFromList(p1,graphList))
	endFor
	selectionToggle = 1
endIf
End

// adds hook to a graph
Function allowSelectionInGraph(targetGraph)
String targetGraph
If(!strlen(targetGraph))
	Setwindow kwTopWin hook(contextual)=contextualwindowhook
Else
	Setwindow $targetGraph hook(contextual)=contextualwindowhook
endIf
end

Function disallowSelectionInGraph(targetGraph)
String targetGraph
If(!strlen(targetGraph))
	Setwindow kwTopWin hook(contextual)=discontextualwindowhook
Else
	Setwindow $targetGraph hook(contextual)=discontextualwindowhook
endIf
end

Static Function AfterWindowCreatedHook(windowName, wt)
String windowName
Variable wt
If(!exists("root:Packages:selectionToggle"))
	Variable/G root:Packages:selectionToggle = 0
endIf
NVAR selectionToggle = root:Packages:selectionToggle
If(selectionToggle && wt==1)
	allowSelectionInGraph(windowName)
	return 1
endIf
return 0
End

Function disContextualwindowhook(hs)
Struct WMWinHookStruct &hs
Variable ret=0
return ret
end

Menu "Spectrometry"
	"Toggle Context Menu", /Q, toggleSelectionInAllGraphs()
End

Function/S contourCheck()
If(strlen(ContourNameList("",";")))
	Return "Modify Contour Appearance"
Else
	Return "Modify Contour Appearance("
endIf
End

Function/S imageCheck()
If(strlen(ImageNameList("",";")))
	Return "Modify Image Appearance"
Else
	Return "Modify Image Appearance("
endIf
End

Function/S traceCheck()
If(strlen(TraceNameList("",";",2)) || strlen(TraceNameList("",";",1)))
	Return "Modify Trace Appearance"
Else
	Return "Modify Trace Appearance("
endIf
End

Function/S reorderCheck()
If(!(strlen(TraceNameList("",";",2)) || strlen(TraceNameList("",";",1))) && strlen(ImageNameList("",";")))
	Return "Reorder Traces("
Else
	Return "Reorder Traces"
endIf
End

Function toggleCrossHair(cursorName,type)
String cursorName
Variable type
String info = CsrInfo($cursorName)
If(strsearch(info,"H="+num2str(type),0) == -1)
	Cursor/M /H=(type) $cursorName
Else
	Cursor/M /H=0 $cursorName
endIf
End

Function marqueeZoom(flag,scale)
Variable flag,scale
String listOfAxis = AxisList(WinName(0,1))
Variable p1
For(p1 = 0; p1 < itemsInList(listOfAxis); p1 += 1)
	GetMarquee/K/Z $stringFromList(p1,listOfAxis)
	String axisType = StringByKey("AXTYPE", AxisInfo(WinName(0,1),stringFromList(p1,listOfAxis)))
	If((stringMatch(axisType,"Left") || stringMatch(axisType,"Right")) && (flag & 2^0))
		If(scale)
			SetAxis/Z $stringFromList(p1,listOfAxis),V_bottom,V_top
		Else
			
		endif
	ElseIf((stringMatch(axisType,"Top") || stringMatch(axisType,"Bottom")) && (flag & 2^1))
		If(scale)
			SetAxis/Z $stringFromList(p1,listOfAxis),V_left,V_right
		Else
			
		endIf
	endIf
endFor
End

Function WaterfallFromList(waveListStr)
String waveListStr
Concatenate/O waveListStr, $(NameOfWave($stringFromList(0,waveListStr))+"_WF")
NewWaterfall $(NameOfWave($stringFromList(0,waveListStr))+"_WF")
Duplicate/O $(NameOfWave($stringFromList(0,waveListStr))+"_WF"),$(NameOfWave($stringFromList(0,waveListStr))+"_WFI")
Wave waterFallColorIndex = $(NameOfWave($stringFromList(0,waveListStr))+"_WFI")
waterFallColorIndex = y
ModifyGraph negRGB=(0,0,0),zColor($(NameOfWave($stringFromList(0,waveListStr))+"_WF"))={waterFallColorIndex,*,*,Rainbow}
ModifyWaterFall hidden=3
End

Function applyTraceShiftAllGraphsWaves()
GetLastUserMenuInfo
NewDataFolder/O/S root:Packages
String graphList = "", selectedTrace=S_traceName, selectedGraph = S_graphName
Wave selectedWave = TraceNameToWaveRef(S_graphName,S_traceName)
String waveFolder = GetWavesDataFolder(selectedWave,0)
graphList = WinList("*", ";", "WIN:1")		// All graph windows.
String selectedTraceInfo = getTraceInfo(S_graphName,S_traceName)
Variable selectedXoffSet
sscanf StringByKey("offset(x)",selectedTraceInfo,"=",";"),"{%f,%*f}",selectedXoffSet
Variable p1,p2
For(p1 = 0; p1 < ItemsInList(graphList); p1 += 1)
	String listOfTraces = TraceNameList(stringFromList(p1,graphList),";",1)
	For(p2 = 0; p2 < ItemsInList(listOfTraces); p2 += 1)
		If(stringMatch(waveFolder,GetWavesDataFolder(TraceNameToWaveRef(StringFromList(p1,graphList),stringFromList(p2,listOfTraces)),0)))
			String currentTraceInfo = getTraceInfo(StringFromList(p1,graphList),stringFromList(p2,listOfTraces))
			Variable currentXoffSet,currentYoffSet
			sscanf StringByKey("offset(x)",currentTraceInfo,"=",";"),"{%f,%f}",currentXoffSet,currentYoffSet
			ModifyGraph /W=$StringFromList(p1,graphList) offset($stringFromList(p2,listOfTraces))={selectedXoffSet,currentYoffSet}
		endIf
	endFor
endFor

End

Function applyAllShiftsAllGraphsWaves()
Variable p1,p2,p3
String graphList = ""
graphList = WinList("*", ";", "WIN:1")		// All graph windows.
String selectedTraceList = TraceNameList("",";",1)
For(p3 = 0; p3 < itemsInList(selectedTraceList); p3 += 1)
	Wave selectedWave = TraceNameToWaveRef("",stringFromList(p3,selectedTraceList))
	DFREF selectedWaveFolder = GetWavesDataFolderDFR(selectedWave)
	String selectedTraceInfo = getTraceInfo("",stringFromList(p3,selectedTraceList))
	Variable selectedXoffSet
	sscanf StringByKey("offset(x)",selectedTraceInfo,"=",";"),"{%f,%*f}",selectedXoffSet
For(p1 = 0; p1 < ItemsInList(graphList); p1 += 1)
	String listOfTraces = TraceNameList(stringFromList(p1,graphList),";",1)
	For(p2 = 0; p2 < ItemsInList(listOfTraces); p2 += 1)
		DFREF waveDataFolder = GetWavesDataFolderDFR(TraceNameToWaveRef(StringFromList(p1,graphList),stringFromList(p2,listOfTraces)))
		If(DataFolderRefsEqual(selectedWaveFolder,waveDataFolder))
			String currentTraceInfo = getTraceInfo(StringFromList(p1,graphList),stringFromList(p2,listOfTraces))
			Variable currentXoffSet,currentYoffSet
			sscanf StringByKey("offset(x)",currentTraceInfo,"=",";"),"{%f,%f}",currentXoffSet,currentYoffSet
			ModifyGraph /W=$StringFromList(p1,graphList) offset($stringFromList(p2,listOfTraces))={selectedXoffSet,currentYoffSet}
			Variable r,g,b
			sscanf StringByKey("rgb(x)",selectedTraceInfo,"=",";"),"(%f,%f,%f)",r,g,b
			ModifyGraph /W=$StringFromList(p1,graphlist) rgb($stringFromList(p2,listOfTraces))=(r,g,b)
		endIf
	endFor
endFor
endFor

End

Function stackTraces()
String selectedTraceList = TraceNameList("",";",5)
Variable p1
For(p1 = 0; p1 < itemsInList(selectedTraceList); p1 += 1)
	String selectedTraceInfo = getTraceInfo("",stringFromList(p1,selectedTraceList))
	Variable selectedXoffset, selectedYoffSet, selectedXmul, selectedYmul
	sscanf StringByKey("offset(x)",selectedTraceInfo,"=",";"),"{%f,%f}",selectedXoffSet, selectedYoffSet
	sscanf StringByKey("muloffset(x)",selectedTraceInfo,"=",";"),"{%f,%f}",selectedXmul, selectedYmul
	if(!selectedYmul)
		selectedYmul = 1
	endif
	if(!selectedXmul)
		selectedXmul = 1
	endif
	String axisName = stringByKey("YAXIS", TraceInfo("","",0))
	GetAxis/Q $axisName
	Variable stackStep = abs(V_max-V_min)/itemsInList(selectedTraceList)
	ModifyGraph offset($stringFromList(p1,selectedTraceList))={selectedXoffSet,selectedYoffset+stackStep*p1}
endFor
End

Function PlotallCores()
String topGraph = WinName(0,1)
String selectedTraceList = TraceNameList(topGraph,";",5)
DFREF currentDataFolder = GetDataFolderDFR()
SetDataFolder root:SensitivityFactors
DFREF coreDataFolder = GetDataFolderDFR()
SetDataFolder currentDataFolder
String coreList =  ReplaceString(",",ReplaceString("WAVES:",DataFolderDIR(2,coreDataFolder),""),";")
Variable p1,p2,p3
For(p1 = 0; p1 < itemsInList(selectedTraceList); p1 += 1)
	DFREF waveDataFolder = GetWavesDataFolderDFR(TraceNameToWaveRef(topGraph,stringFromList(p1,selectedTraceList)))
	String waveDataFolderStr = GetWavesDataFolder(TraceNameToWaveRef(topGraph,stringFromList(p1,selectedTraceList)),1)
	String wavesList = ReplaceString(",",ReplaceString("WAVES:",DataFolderDIR(2,waveDataFolder),""),";")
	For(p2 = 0; p2 < itemsInList(wavesList); p2 += 1)
		If(stringMatch(stringFromList(p2,wavesList),"BE_*"))
		elseIf(stringMatch(stringFromList(p2,wavesList),"*_angCorr"))
		else
			For(p3 = 0; p3 < itemsInList(coreList); p3 += 1)
				If(stringMatch(stringFromList(p2,wavesList),stringFromList(p3,coreList)+"*") && !stringMatch(stringFromList(p2,wavesList),NameOfWave(TraceNameToWaveRef(topGraph,stringFromList(p1,selectedTraceList)))))
					 if(!checkName(stringFromList(p2,wavesList),1))
					 	Preferences 1
					 	DoWindow $(topGraph + "_" + stringFromList(p3,coreList))
					 	Print topGraph +"_" + stringFromList(p3,coreList)
						if(!V_flag)
							Display /N=$(topGraph +"_" + stringFromList(p3,coreList)) $(waveDataFolderStr + stringFromList(p2,wavesList))
						else
							AppendToGraph /W=$(topGraph +"_" + stringFromList(p3,coreList)) $((waveDataFolderStr + stringFromList(p2,wavesList)))
					 	endif
					 	Preferences 0
					 endif
				endIf
			endFor
		endIf
	endFor
endFor
End